Repository navigation
fix(release): authenticate the manifest push as a GitHub App - #2643
Conversation
The manifest job has failed every release since 2026-07-20, freezing the channel pointers: stable at 5.260720.10 and dev at 5.260723.8, while v5.260724.1 published 12 assets that no channel can reach and the v5.260724.2 promotion tag has no release at all. Root cause is not the credential's scope. The 'main' ruleset (id 9203218) carries a pull_request rule with an EMPTY bypass_actors list, so every direct push to main is rejected GH013 no matter how the pusher authenticates. The deploy key failed that way (deploy keys are also disabled org-wide), and the fine-grained PAT that replaced it failed the same way — the preflight passed on 07-24 and the push still 403'd. An App is the narrowest identity that can hold a ruleset bypass; granting it to a RepositoryRole would hand every admin direct push to main and undo the least-privilege posture F16-F18 established. So the job now mints a short-lived App token per run (expires ~1h, nothing long-lived can push to main) and checks out with it. - release-publish.yml: preflight requires RELEASE_MANIFESTS_APP_ID and RELEASE_MANIFESTS_APP_PRIVATE_KEY, mints via create-github-app-token pinned to fee1f7d6 (v3.2.0), checkout uses the minted token; HUMAN SETUP header rewritten with the App + ruleset-bypass provisioning steps and the exact gh api bypass command - push-rejection diagnostic now names the ruleset bypass, not just scope - release.yml / version.yml: secrets-inherit comments follow the rename - release-docs.test.ts: the contract test pinned the PAT model; it now pins the App model and asserts the PAT wiring is gone Requires one-time provisioning before the next release: create the App, store its credentials in the release-manifests environment, and add it as an Integration bypass actor on ruleset 9203218.
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 265c809351
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # gh api repos/automagik-dev/genie/rulesets/9203218 -X PUT \ | ||
| # -f 'bypass_actors[][actor_type=Integration]' \ | ||
| # -F 'bypass_actors[][actor_id]=<APP_ID>' \ | ||
| # -f 'bypass_actors[][bypass_mode]=always' |
There was a problem hiding this comment.
Correct the ruleset bypass provisioning command
When an administrator follows this required one-time setup, the two -f arguments put the values inside the field brackets (bypass_actors[][actor_type=Integration]) rather than using the nested-field syntax bypass_actors[][actor_type]=Integration required by gh api. Moreover, PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} expects the ruleset definition, so the command should first preserve the existing name, enforcement, conditions, rules, and bypass actors instead of submitting only the new actor. As written, provisioning fails or risks replacing existing rules, leaving the App without the bypass and every manifest publication blocked by GH013.
Useful? React with 👍 / 👎.
The org-wide deploy-key ban made the ssh model unusable, and the fine-grained PAT that replaced it still could not push: the 'main' ruleset carried a pull_request rule with an empty bypass_actors list, so every direct push was rejected GH013 regardless of token scope. That froze the channel pointers from 2026-07-20 onward. Resolved without touching the deploy-key policy: PR automagik-si#2643 (promoted in automagik-si#2644 as 73bd48a) mints a per-run GitHub App token — genie-release-bot, app id 4393439, contents:write + metadata:read only, installed on this repository alone, sole ruleset bypass actor Integration:4393439:always. No user, role, or Actions bypass was added, and the token expires in ~1h so no long-lived credential can push to main. The dev/homolog criterion stays UNCHECKED until a post-merge dev release actually advances a channel manifest — this commit is that release's trigger.
…onstration Codex P2 on PR automagik-si#2702 caught the closure commit leaving the wish internally contradictory: the G2 acceptance criterion, the QA criterion, two Review Results closure sentences, and INDEX's pr-2545 line still said no live two-maintainer run had been captured / stable promotion remained BLOCKED. All five sites now record the evidence: stable run 30240023804 (v5.260727.5) — automagik-genie dispatched, independent maintainer approved (prevent_self_review), 36 immutable assets, all three manifests advanced; credential half landed as the genie-release-bot App (automagik-si#2643/automagik-si#2644).
The release pipeline has been silently broken since 2026-07-20
Every release since then failed at "Advance authoritative channel manifests", freezing the channel pointers:
Meanwhile
v5.260724.1published 12 assets that no channel can reach, andv5.260724.2(the #2624 promotion tag) has no release at all. Nothing merged after Jul 23 is installable.Root cause: the ruleset, not the credential
The
mainruleset (id9203218, enforcementactive) carries apull_requestrule with an emptybypass_actorslist. Every direct push tomainis rejectedGH013regardless of how the pusher authenticates.That is why two credential models in a row failed the same way:
github-actions[bot]→ 403;GH013.The workflow's own diagnostic blamed token scope, which sent the last fix down the wrong path.
Fix: mint a short-lived App token
A GitHub App is the narrowest identity that can hold a ruleset bypass. Granting the bypass to a
RepositoryRoleinstead would hand every admin direct push tomain, undoing the least-privilege posture F16–F18 established in the stable-release security gate.RELEASE_MANIFESTS_APP_ID+RELEASE_MANIFESTS_APP_PRIVATE_KEYactions/create-github-app-tokenpinned tofee1f7d6(v3.2.0) — expires in ~1h, so no long-lived credential can push tomainHUMAN SETUPheader rewritten with App provisioning steps and the exactgh apibypass commandrelease-docs.test.tspinned the PAT model; it now pins the App model and asserts the PAT wiring is gonesecrets: inheritalready exists in both callers, so the new secrets propagate with no change to the call chain.Required one-time provisioning (before this can work)
genie-release-bot) — Repository permissions → Contents: Read and write, nothing else. Generate a private key.automagik-dev/genieonly.RELEASE_MANIFESTS_APP_IDandRELEASE_MANIFESTS_APP_PRIVATE_KEYto therelease-manifestsenvironment.9203218.RELEASE_MANIFESTS_TOKENsecret.Verification: 46 pass / 0 fail on
release-docs.test.ts+reconcile-release-note.test.ts; all three workflows parse as valid YAML; every external action in the file remains pinned to a 40-hex SHA.